home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / rpc / rpcDispatch.c < prev    next >
C/C++ Source or Header  |  1991-02-12  |  17KB  |  559 lines

  1. /*
  2.  * rpcDispatch.c --
  3.  *
  4.  * The top level rpc dispatch routine.  The dispatcher is responsible for
  5.  * taking a packet from the packet transport level and passing it to the
  6.  * delivery level of the correct process involved in the RPC.  The
  7.  * top-level dispatcher finds the protocol state for the client or server
  8.  * receiving the message and calls the client or server specific dispatch
  9.  * routine.  This file also has the utility routine to copy a message from
  10.  * the network module's buffers into the stub's buffers.
  11.  *
  12.  * Copyright 1985 Regents of the University of California
  13.  * All rights reserved.
  14.  */
  15.  
  16. #ifndef lint
  17. static char rcsid[] = "$Header: /sprite/src/kernel/rpc/RCS/rpcDispatch.c,v 9.17 91/02/12 14:15:44 jhh Exp $ SPRITE (Berkeley)";
  18. #endif /* not lint */
  19.  
  20. #include <sprite.h>
  21. #include <stdio.h>
  22. #include <bstring.h>
  23. #include <string.h>
  24. #include <dbg.h>
  25. #include <vm.h>
  26.  
  27. #include <rpc.h>
  28. #include <rpcClient.h>
  29. #include <rpcServer.h>
  30. #include <rpcTrace.h>
  31. #include <rpcInt.h>
  32. #include <net.h>
  33.  
  34. /*
  35.  * Our sprite ID.  It is exported for general use by other modules.
  36.  * This is set by a reverse arp transaction at boot time (see Rpc_Start),
  37.  * or if that fails, by the rpc dispatcher who monitors the clientID field of
  38.  * rpc reply messages (see RpcClientDispatch).  Finally, if neither of
  39.  * those hooks work, a diskfull node will set its address by looking at
  40.  * the disk header (see FsAttachDisk).
  41.  *
  42.  * Important: servers won't respond to requests until their rpc_SpriteID is set.
  43.  */
  44. int    rpc_SpriteID = 0;
  45.  
  46. /*
  47.  * We stop handlling requests during a bad trap that causes us
  48.  * to sync our disks.  If that deadlocks we want to be sure that
  49.  * the RPC system is off so we can't hang other machines.
  50.  */
  51. extern int sys_ErrorSync;
  52.  
  53. /*
  54.  * While testing there may be many version mismatch errors.  If
  55.  * rpc_PrintMismatch is FALSE, then we only report a few of these errors
  56.  * every once in a while.
  57.  */
  58. int mismatchErrors = 0;
  59.  
  60. /*
  61.  * An array of bitmasks is kept for faster comparisions by the dispatcher.
  62.  * Indexed by the total number of fragments in the packet, the array
  63.  * contains a complete bitmask for that many fragments.
  64.  */
  65. unsigned int rpcCompleteMask[17] = {
  66.     0x0000, 0x0001, 0x0003, 0x0007, 0x000F,
  67.         0x001F, 0x003F, 0x007F, 0x00FF,
  68.         0x01FF, 0x03FF, 0x07FF, 0x0FFF,
  69.         0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };
  70. /*
  71.  * Forward declarations.
  72.  */
  73. static Boolean ValidateClient _ARGS_((Net_Interface *interPtr, int protocol,
  74.         Address headerPtr, RpcHdr *rpcHdrPtr));
  75. static void VersionMismatch _ARGS_((Net_Interface *interPtr, int protocol,
  76.         Address headerPtr, RpcHdr *rpcHdrPtr, int packetLength));
  77.  
  78.  
  79.  
  80.  
  81. /*
  82.  *----------------------------------------------------------------------
  83.  *
  84.  * Rpc_Dispatch --
  85.  *
  86.  *      This does some consistency checks on an incoming packet, finds the
  87.  *      protocol state for the packet (either client or server) and then
  88.  *      calls either the server or client dispatch routine.
  89.  *
  90.  *    This still has a few ethernet specfich things that should be fixed.
  91.  *
  92.  * Results:
  93.  *    None.
  94.  *
  95.  * Side effects:
  96.  *    This may drop a packet if various consistency checks fail.
  97.  *
  98.  *----------------------------------------------------------------------
  99.  */
  100. void
  101. Rpc_Dispatch(interPtr, protocol, headerPtr, rpcHdrAddr, packetLength)
  102.     Net_Interface *interPtr;    /* Network interface where we got the packet. */
  103.     int        protocol;    /* Network protocol of packet. */
  104.     Address    headerPtr;    /* Pointer to transport header. */
  105.     Address     rpcHdrAddr;    /* RPC header of packet. */
  106.     int        packetLength;        /* Size of RPC packet. */
  107. {
  108.     register RpcHdr    *rpcHdrPtr; /* RPC header of packet. */
  109.     register int expectedLength;
  110.     extern int ultra;
  111.  
  112.  
  113.     if (ultra) {
  114.     printf("In Rpc_Dispatch\n");
  115.     }
  116.     rpcHdrPtr = (RpcHdr *) rpcHdrAddr;
  117.     if (packetLength < sizeof(RpcHdr)) {
  118.     rpcCltStat.shorts++;
  119.     printf("Rpc_Dispatch: SHORT packet, (%d) less than RpcHdr\n",
  120.                   packetLength, sizeof(RpcHdr));
  121.     printf("Resetting network interface %s\n",
  122.         interPtr->name);
  123.     Net_Reset(interPtr);
  124.     return;
  125.     }
  126.     if (rpcHdrPtr->version == rpc_SwappedVersion ||
  127.     rpcHdrPtr->version == rpc_SwappedVersionNew) {
  128.     /*
  129.      * Byte swap the packet header and the parameter block.
  130.      */
  131.     if (!RpcByteSwapInComing(rpcHdrPtr, packetLength)) {
  132.         printf("Warning: Rpc_Dispatch failed byte-swap.\n");
  133.         return;
  134.     }
  135.     } else if (rpcHdrPtr->version != rpc_NativeVersion &&
  136.         rpcHdrPtr->version != rpc_NativeVersionNew) {
  137.     /*
  138.      * Keep a short list of hosts that aren't talking the
  139.      * right version of RPC.  Attempt to print out one message
  140.      * about this per host, and then keep quiet.
  141.      */
  142.     VersionMismatch(interPtr, protocol, headerPtr, rpcHdrPtr, packetLength);
  143.     return;
  144.     }
  145.     if (rpc_SanityCheck) {
  146.     Net_ScatterGather    scatter;
  147.     ReturnStatus        status;
  148.     scatter.bufAddr = (Address) rpcHdrAddr;
  149.     scatter.length = packetLength;
  150.     status = Rpc_SanityCheck(1, &scatter, packetLength);
  151.     if (status != SUCCESS) {
  152.         return;
  153.     }
  154.     }
  155.     expectedLength =  sizeof(RpcHdr) +
  156.              rpcHdrPtr->paramSize +
  157.              rpcHdrPtr->dataSize;
  158.     if (packetLength < expectedLength) {
  159.     rpcCltStat.shorts++;
  160.     printf("Rpc_Dispatch: SHORT packet, (%d) not (%d), ",
  161.                   packetLength, expectedLength);
  162.     printf("srv %d clt %d rpc %d\n", rpcHdrPtr->serverID,
  163.             rpcHdrPtr->clientID, rpcHdrPtr->command);
  164.     printf("Resetting network interface %s\n",
  165.         interPtr->name);
  166.     Net_Reset(interPtr);
  167.     return;
  168.     } else if (packetLength > expectedLength &&
  169.            packetLength > interPtr->minBytes) {
  170.     /*
  171.      * Short messages (like acks and null replies)
  172.      * get padded to minimum  packet length.  Other messages
  173.      * get padded to 4 byte alignments.
  174.      */
  175.     rpcCltStat.longs++;
  176.     if (packetLength > interPtr->maxBytes) {
  177.         printf("Received oversized packet\n");
  178.         printf("Resetting network interface\n");
  179.         Net_Reset(interPtr);
  180.         return;
  181.     }
  182.     }
  183.  
  184.     RPC_TRACE(rpcHdrPtr, RPC_INPUT, "Input");
  185.  
  186.     if (rpcHdrPtr->flags & RPC_SERVER) {
  187.     register RpcServerState *srvPtr;
  188.     /*
  189.      * Don't do anything if we don't know who we are.  This occurs
  190.      * at boot time if we get a request before doing reverse ARP.
  191.      * Also, don't do anything in the middle of a panic.  If a host
  192.      * deadlocks trying to enter the debugger, then callback RPCs
  193.      * from file servers should not also hang.
  194.      */
  195.     if (rpc_SpriteID == 0 || sys_ErrorSync) {
  196.         return;
  197.     }
  198.     if (rpcHdrPtr->serverID != RPC_BROADCAST_SERVER_ID &&
  199.         rpcHdrPtr->serverID != rpc_SpriteID) {
  200.         /*
  201.          * A bug, or the Intel chip is wack-o.
  202.          */
  203.         if (rpcHdrPtr->serverID > 0 &&
  204.         rpcHdrPtr->serverID < NET_NUM_SPRITE_HOSTS) {
  205.         char    addrBuffer[128];
  206.         Net_HdrDestString(interPtr->netType, protocol,headerPtr, 128, 
  207.             addrBuffer);
  208.         printf("Warning: Rpc_Dispatch, wrong server ID %d\n",
  209.             rpcHdrPtr->serverID);
  210.         printf("\tRPC %d flags %x Client %d at address: %s\n",
  211.                rpcHdrPtr->command, rpcHdrPtr->flags,
  212.                rpcHdrPtr->clientID, addrBuffer);
  213.  
  214.         } else {
  215.         printf("Rpc_Dispatch: junk serverID %d from client %d\n",
  216.                 rpcHdrPtr->serverID,
  217.                 rpcHdrPtr->clientID);
  218.         }
  219.         printf("Resetting network interface %s\n", interPtr->name);
  220.         Net_Reset(interPtr);
  221.         return;
  222.     }
  223.  
  224.     rpcSrvStat.toServer++;
  225.  
  226.     /*
  227.      * Verify or initialize the sprite host id for the client
  228.      * (clientID) from the transport level source address.
  229.      * This doesn't usually kick in unless the client can't do reverse arp.
  230.      */
  231.     if ( ! ValidateClient(interPtr, protocol, headerPtr, rpcHdrPtr)) {
  232.         rpcSrvStat.invClient++;
  233.         return;
  234.     }
  235.  
  236.     /*
  237.      * Save sender's requested interfragment delay.
  238.      */
  239.     rpcDelay[rpcHdrPtr->clientID] = rpcHdrPtr->delay;
  240.     /*
  241.      * Match the input message to a server process.
  242.      */
  243.     srvPtr = RpcServerAlloc(rpcHdrPtr);
  244.     if (srvPtr == (RpcServerState *)NIL) {
  245.         /*
  246.          * Is it okay to check this here?
  247.          */
  248.         if (rpcServiceEnabled) {
  249.         rpcSrvStat.noAlloc++;
  250.         if (rpcSendNegAcks) {
  251.             RpcServerDispatch(srvPtr, rpcHdrPtr);
  252.         }
  253.         }
  254.     } else {
  255.         RpcServerDispatch(srvPtr, rpcHdrPtr);
  256.     }
  257.     } else {
  258.     /*
  259.      * Get the channel for the packet.
  260.      */
  261.     register RpcClientChannel *chanPtr;
  262.  
  263.     rpcCltStat.toClient++;
  264.     if (rpcHdrPtr->channel < 0 ||
  265.         rpcHdrPtr->channel >= rpcNumChannels) {
  266.         rpcCltStat.badChannel++;
  267.         printf("Rpc_Dispatch: bad channel %d from clt %d rpc %d",
  268.            rpcHdrPtr->channel, rpcHdrPtr->clientID, rpcHdrPtr->command);
  269.         printf("Resetting network interface %s\n", interPtr->name);
  270.         Net_Reset(interPtr);
  271.     } else {
  272.         /*
  273.          * Save sender's requested interfragment delay,
  274.          * then dispatch to client process.
  275.          */
  276.         if (rpcHdrPtr->serverID < NET_NUM_SPRITE_HOSTS &&
  277.         rpcHdrPtr->serverID > 0) {
  278.         rpcDelay[rpcHdrPtr->serverID] = rpcHdrPtr->delay;
  279.         }
  280.         chanPtr = rpcChannelPtrPtr[rpcHdrPtr->channel];
  281.         if (ultra) {
  282.         printf("Calling RpcClientDispatch\n");
  283.         }
  284.         RpcClientDispatch(chanPtr, rpcHdrPtr);
  285.     }
  286.     }
  287. }
  288.  
  289.  
  290. /*
  291.  *----------------------------------------------------------------------
  292.  *
  293.  * RpcScatter --
  294.  *
  295.  *    Copy the data in the network buffers into the buffers
  296.  *    specified by the scatter vector.  This routine only works
  297.  *    on RPC messages.  It knows the RPC packet format:
  298.  *      The Rpc header, which includes the sizes of the next two parts.
  299.  *      The parameter area.
  300.  *      The data area.
  301.  *    The scatter vector lengths of the last two parts are used
  302.  *    as maximum buffer sizes.  The actual sizes of the parts is
  303.  *    taken from the rpc header.  This is done because the RPC system
  304.  *    preallocates buffers which are large enough to handle any message.
  305.  *
  306.  * Results:
  307.  *    None.
  308.  *
  309.  * Side effects:
  310.  *    The copy.
  311.  *
  312.  *----------------------------------------------------------------------
  313.  */
  314. void
  315. RpcScatter(rpcHdrPtr, bufferPtr)
  316.     register RpcHdr *rpcHdrPtr;        /* The Rpc Header as it sits in the
  317.                      * network's buffer.  The data follows
  318.                      * the header directly. */
  319.     RpcBufferSet *bufferPtr;        /* Specification of the buffers to
  320.                      * copy the message to. */
  321. {
  322.     register Address netBufPtr;        /* A pointer in to network buffer */
  323.     register int length;        /* Copying length */
  324.     int destLength;            /* length of destination buffers */
  325.     Boolean    newVersion = FALSE;
  326.     RpcHdrNew    *newHdrPtr = (RpcHdrNew *) rpcHdrPtr;
  327.  
  328.     if (rpcHdrPtr->version == rpc_NativeVersionNew) {
  329.     newVersion = TRUE;
  330.     }
  331.     netBufPtr = (Address)rpcHdrPtr;
  332.  
  333.     /*
  334.      * Copy the RPC header.
  335.      */
  336.     length = bufferPtr->rpcHdrBuffer.length;
  337.     bcopy(netBufPtr, bufferPtr->rpcHdrBuffer.bufAddr, length);
  338.     if (newVersion) {
  339.     netBufPtr = ((Address) rpcHdrPtr) + newHdrPtr->paramStart;
  340.     } else {
  341.     netBufPtr += length;
  342.     }
  343.     /*
  344.      * Copy the parameter and data areas.  Their sizes are in
  345.      * the RPC header.  Complain if either area is too large.
  346.      */
  347.     length = rpcHdrPtr->paramSize;
  348.     if (length != 0) {
  349.     destLength = bufferPtr->paramBuffer.length;
  350.     if (length + rpcHdrPtr->paramOffset > destLength) {
  351.         rpcCltStat.paramOverrun++;
  352.         printf("RpcScatter: rpc %d param size + off (%d + %d) > (%d)\n",
  353.                rpcHdrPtr->command, length, rpcHdrPtr->paramOffset,
  354.                destLength);
  355.         if (rpcHdrPtr->paramOffset < destLength) {
  356.         length = destLength - rpcHdrPtr->paramOffset;
  357.         } else {
  358.         length = 0;
  359.         }
  360.     }
  361.     bcopy(netBufPtr, bufferPtr->paramBuffer.bufAddr +
  362.                      rpcHdrPtr->paramOffset, length);
  363.     if (!newVersion) {
  364.         netBufPtr += rpcHdrPtr->paramSize;
  365.     }
  366.     }
  367.     if (newVersion) {
  368.     netBufPtr = ((Address) rpcHdrPtr) + newHdrPtr->dataStart;
  369.     }
  370.     length = rpcHdrPtr->dataSize;
  371.     if (length != 0) {
  372.     destLength = bufferPtr->dataBuffer.length;
  373.     if (length + rpcHdrPtr->dataOffset > destLength) {
  374.     /*
  375.      * The returned data is more than we expect.  One reason for
  376.      * this is that the Intel driver limits the size of the data area and
  377.      * parameter area to be 0, or to be greater than 12 bytes because
  378.      * of the Intel DMA hardware.
  379.      */
  380.         rpcCltStat.dataOverrun++;
  381.         if (rpcHdrPtr->dataOffset < destLength) {
  382.         length = destLength - rpcHdrPtr->dataOffset;
  383.         } else {
  384.         length = 0;
  385.         }
  386.     }
  387.     bcopy(netBufPtr, bufferPtr->dataBuffer.bufAddr + rpcHdrPtr->dataOffset,
  388.         length);
  389.     }
  390. }
  391.  
  392. /*
  393.  *----------------------------------------------------------------------
  394.  *
  395.  * ValidateClient --
  396.  *
  397.  *      Check the clientID field of an incoming Rpc request.  Invalid ID's
  398.  *      are screened out, and the special clientID of zero is overwritten
  399.  *      with the client's true sprite ID.  This is done by looking the
  400.  *      client's physical address up in a table with Net_AddrToID.  This
  401.  *      true sprite ID is propogated back to clients so they can determine
  402.  *      their own sprite ID.  This should be replaced by the use of
  403.  *    Reverse Arp on clients at boot time.
  404.  *
  405.  * Results:
  406.  *      FALSE if clientID is invalid or the physical address of the client
  407.  *      isn't in the table.  TRUE otherwise - this gurantees a valid
  408.  *      clientID in the RpcHdr.
  409.  *
  410.  * Side effects:
  411.  *      Muck with the header so that subsequent users of the RpcHdr see a
  412.  *      valid clientID field.
  413.  *
  414.  *----------------------------------------------------------------------
  415.  */
  416. static Boolean
  417. ValidateClient(interPtr, protocol, headerPtr, rpcHdrPtr)
  418.     Net_Interface *interPtr;    /* Network interface. */
  419.     int        protocol;    /* Network protocol of packet. */
  420.     Address    headerPtr;    /* Transport header. */
  421.     RpcHdr      *rpcHdrPtr;
  422. {
  423.     register int        clientID;
  424.     register Boolean        result = FALSE;
  425.  
  426.     clientID = rpcHdrPtr->clientID;
  427.  
  428.     if (clientID > 0 && clientID < NET_NUM_SPRITE_HOSTS) {
  429.     /*
  430.      * A potentially valid clientID.  We don't need to
  431.      * save the client's transport address because the
  432.      * we can get that from the saved request message.
  433.      */
  434.     result = TRUE;
  435.     } else if (clientID == 0) {
  436.     /*
  437.      * Look client's transport address up in our in core host table.
  438.      */
  439.     clientID = Net_HdrToID(interPtr->netType, protocol, headerPtr);
  440.         printf("Warning: RpcValidateClient had to set clientID %d\n", clientID);
  441.     if (clientID < 0) {
  442.         char    addrBuffer[128];
  443.         /*
  444.          * Should invoke Reverse ARP to find out the Sprite ID.
  445.          */
  446.         Net_HdrDestString(interPtr->netType, protocol, headerPtr, 128, 
  447.         addrBuffer);
  448.         printf("Client at unknown address: %s\n", addrBuffer);
  449.         result = FALSE;
  450.     } else {
  451.         rpcHdrPtr->clientID = clientID;
  452.         result = TRUE;
  453.     }
  454.     } else {
  455.     result = FALSE;
  456.     printf("Invalid Client Sprite ID (%d)\n", clientID);
  457.     }
  458.     return(result);
  459. }
  460.  
  461. /*
  462.  *----------------------------------------------------------------------
  463.  *
  464.  * VersionMismatch --
  465.  *
  466.  *    This is called upon reciept of a packet with a bad RPC version
  467.  *    number.  This routine keeps a short list of offending hosts,
  468.  *    and will print out a warning about each one it encounters.
  469.  *
  470.  * Results:
  471.  *    None.
  472.  *
  473.  * Side effects:
  474.  *    This adds items to its versionList.
  475.  *
  476.  *----------------------------------------------------------------------
  477.  */
  478. static int numVersions = 0;
  479.  
  480. #define ADDR_LEN    40
  481. typedef struct {
  482.     Net_Interface    *interPtr;    /* Network interface. */
  483.     int protocol;            /* The packet protocol. */
  484.     int count;                /* Count of mismatches */
  485.     char sourceAddr[ADDR_LEN];        /* Storage for source addr string */
  486. } VersionRecord;
  487.  
  488. #define NUM_VERSIONS    4
  489. static VersionRecord versionList[NUM_VERSIONS];
  490.  
  491. static void
  492. VersionMismatch(interPtr, protocol, headerPtr, rpcHdrPtr, packetLength)
  493.     Net_Interface *interPtr;    /* Network interface. */
  494.     int        protocol;    /* Network protocol of packet. */
  495.     Address    headerPtr;    /* Pointer to transport header. */
  496.     RpcHdr    *rpcHdrPtr;    /* RPC header of packet. */
  497.     int        packetLength;    /* Size of RPC packet. */
  498. {
  499.     char addrBuffer[ADDR_LEN];
  500.     int i;
  501.     char *type;
  502.     char *proto;
  503.  
  504.     /*
  505.      * Get a string value for the sender of the packet and see if
  506.      * we've already gotten a bad packet from this host.
  507.      */
  508.     Net_HdrDestString(interPtr->netType, protocol, headerPtr, ADDR_LEN, 
  509.         addrBuffer);
  510.  
  511.     for (i=0 ; i<numVersions ; i++) {
  512.     if (strcmp(versionList[i].sourceAddr, addrBuffer) == 0) {
  513.         versionList[i].count++;
  514.         return;
  515.     }
  516.     }
  517.     if (numVersions >= NUM_VERSIONS) {
  518.     /*
  519.      * Bail out if we don't have room in the versionList.
  520.      * Alternatively we could replace an entry in the versionList.
  521.      */
  522.     return;
  523.     }
  524.  
  525.     switch(interPtr->netType) {
  526.     case NET_NETWORK_ETHER: 
  527.         type = "ether";
  528.         break;
  529.     default:
  530.         type = "unknown network type";
  531.         break;
  532.     }
  533.     switch(protocol) {
  534.     case NET_PROTO_RAW:
  535.         proto = "raw";
  536.         break;
  537.     case NET_PROTO_INET:
  538.         proto = "inet";
  539.         break;
  540.     default:
  541.         proto = "unknown network protocol";
  542.         break;
  543.     }
  544.     printf("RPC Version mismatch: %x not %x from %s %s %s",
  545.     rpcHdrPtr->version, rpc_NativeVersion, type, proto, addrBuffer);
  546.     if (rpcHdrPtr->clientID > 0 && rpcHdrPtr->clientID < NET_NUM_SPRITE_HOSTS) {
  547.     printf(" clientID %d\n", rpcHdrPtr->clientID);
  548.     } else {
  549.     printf("\n");
  550.     }
  551.     versionList[numVersions].count = 1;
  552.     versionList[numVersions].protocol = protocol;
  553.     versionList[numVersions].interPtr = interPtr;
  554.     strncpy(versionList[numVersions].sourceAddr, addrBuffer, ADDR_LEN);
  555.     numVersions++;
  556.  
  557.     return;
  558. }
  559.